'''
Created on 22 Jul 2013

@author: Matt
'''
import sys
from urllib.parse import quote
from urllib.request import Request, urlopen
from urllib.error import HTTPError
from MattCrypto.CryptoFunctions import hexStrToBits, bytesToBits, intToBits, xor,\
    bitsToHex, hexor

TARGET = 'http://crypto-class.appspot.com/po?er='
#--------------------------------------------------------------
# padding oracle
#--------------------------------------------------------------
class PaddingOracle(object):
    def query(self, q):
        print(q)
        target = TARGET + quote(q)    # Create query URL
        req = Request(target)         # Send HTTP request to server
        try:
            urlopen(req)          # Wait for response
        except HTTPError as e:          
            if e.code == 404:
                print("We got: %d" % e.code)       # Print response code
                return True # good padding
            return False # bad padding

if __name__ == "__main__":
    
    #print(hexor("b7", "64"))
    #print(hexor("d0", "03"))
    #print(hexor(hexor("b7", "64"), "03"))
    
    po = PaddingOracle()
    encryptedString = "f20bdba6ff29eed7b046d1df9fb7000058b1ffb4210a580f748b4ac714c001bd4a61044426fb515dad3f21f18aa577c0bdf302936266926ff37dbf7035d5eeb4"
    
    completeString = ""
    blocks = [encryptedString[0:32], encryptedString[32:64], encryptedString[64:96], encryptedString[96:128]]
        
    validPadC1 = []
    for z in range(2, 3):
        iv = blocks[z]
        c_0 = blocks[z+1]
        
        completeString += "".join([chr(x) for x in validPadC1])
        
        validPadC1 = []
        
        for y in range(2, 17):
            for x in range(0, 256):
                
                guessStr = hex(x)[2:].zfill(2)
                guessStr = hexor(guessStr[0:2], iv[(32 - (2*(y))):(32 - (2*(y-1)))]).zfill(2)
                if (y > 1):
                    guessStr += hexor(iv[(32 - (2*(y-1))):].zfill(2), "".join([hex(x)[2:] for x in validPadC1]).zfill(2))
                positionStr = hex(y)[2:].zfill(2) * y
                guessHex = hexor(guessStr, positionStr).zfill((2*y))
    
                testiv = iv[0:(32 - (2*y))] + guessHex
                
                #print(iv + c_0)
            
                if po.query(testiv + c_0):       # Issue HTTP query with the given argument
                    validPadC1 = [x] + validPadC1
                    print(completeString + "".join([chr(x) for x in validPadC1]))                
                    break;
    print("Done!")